
package Timeline.Core;


import Timeline.Core.Componente.Mouse;
import Timeline.Core.GamePanel.GamePanel;
import Timeline.Core.Level.LevelLoader;
import Timeline.Core.Sound.Player.SoundFactory;
import Timeline.Entidade.GameObject;
import Timeline.Entidade.Tower;
import Timeline.Enumerador.EnumEstado;
import Timeline.Imagem.Imagem;
import Timeline.Jogador.Jogador;
import Timeline.Util.Componente.CustomBox;
import Timeline.Util.Componente.PintaTexto;
import Timeline.Util.Cursor.CursorFactory;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;


public class GameMain extends JFrame {
    
   private static GameMain gameMain;
    
   public static long fps;
   public static int frameCount;
   public static GamePanel gamePanel = new GamePanel();
   private boolean win;
    /**
     * @return the time
     */
    public static int getTime() {
        return time;
    }

   public  EnumEstado state;

   public static CopyOnWriteArrayList<GameObject> objetos;
   public static Mouse mouse;
   public static Jogador jogador;
   public static PintaTexto pintaTexto;
   private static int time;
   
    private GameMain(){ 
    }
    
    private void initialize(){

        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.setBackground(Color.black);
        this.setResizable(false);
        this.setSize(1024,768);
        this.setVisible(true);
        setLoading(this.getGraphics());
        SoundFactory.getSoundPlayer().tocar("Ressource/Sound/game.mp3");  
        carregaComponentes();
        CursorFactory.getCursor().mudarCursor(this);           
        addListerner();
        objetos = new CopyOnWriteArrayList<>();
        setGameState(EnumEstado.iniciandoLevel);
        rodarGameLoop();
        pintaTexto = new PintaTexto();
        
    }
    
    protected void finalize() throws Throwable {
        SoundFactory.getSoundPlayer().parar();
    }
    
    private void carregaComponentes(){
        Container cp = getContentPane();
        GridBagConstraints cons = new GridBagConstraints();  
        GridBagLayout layout = new GridBagLayout();  
        cp.setLayout(layout);
        cons.fill = GridBagConstraints.BOTH;
        cons.weightx = 1;
        cons.insets = new Insets(10,10,10,10);
        cons.gridy = 2;  
        cons.gridx = 0;  
        cons.weighty = 600;
        cp.add(gamePanel, cons);
        cons.gridy = 3;  
        cons.gridx = 0;  
        cons.weighty = 1;
        cp.add(LevelLoader.getInstance().getStore().getTela(), cons); 
    }
    
    private void addListerner(){
        mouse = new Mouse();
        gamePanel.addMouseListener(mouse);
    }
    
    private void update(double delta){
       LevelLoader.getInstance().update(delta);
        for(GameObject obj: objetos){
            obj.update(delta);
        }
    }
    
    private void draw(){
        gamePanel.draw();
    }
    
    public static GameMain getInstance(){
        if(gameMain == null){
            gameMain = new GameMain();
        }
        return gameMain;
    }
   
   private void gameLoop()
   {      
      long tempoUltimoUpdate;
      long tempoUltimoFrame = 0;

      tempoUltimoUpdate = System.nanoTime();

      setLoading(this.getGraphics());
      while (state != EnumEstado.gameover)
      {
          long tempoAgora = System.nanoTime();
          long duracaoUpdate = tempoAgora - tempoUltimoUpdate;
          tempoUltimoUpdate = tempoAgora;
          double delta = duracaoUpdate / ((double)Parametro.TEMPO_IDEAL);

          tempoUltimoFrame += duracaoUpdate;
          fps++;

         switch(state){
             case pause:
                 break;
             case jogando:
                    update(delta);
                    draw();     
                    try {Thread.sleep((tempoUltimoFrame-System.nanoTime() + Parametro.TEMPO_IDEAL)/1000000 );} catch(Exception e) {/*System.out.println(e.getMessage());*/}                  
                break;
             case iniciandoLevel:
                carregarLevel(jogador.getLevel());
                break;
         }

         
          if (tempoUltimoFrame >= 1000000000)
          {
             this.setTitle("Tower Defense - "+ "FPS: "+fps+" time:" + getTime());
             tempoUltimoFrame = 0;
             time++;
             fps = 0;
          }
          
          if(state == EnumEstado.gameover){
              gameOver();
          }

      }
      
      this.dispose();
   }
   
   public void rodarGameLoop()
   {
      Thread loop = new Thread( new Runnable() {
           @Override
           public void run() {
            gameLoop();
           }
       });
        
       loop.start();
     

    }

    public void setGameState(EnumEstado enumState) {
        this.state = enumState;
        
    }
    
    public EnumEstado getGameState() {
        return this.state;
    }
    
    public void carregarLevel(int level){
        LevelLoader.getInstance().levelStart(level);
        setGameState(EnumEstado.jogando);
    }
    
    public void addTower(int posx, int posy, Tower t){
        posx = Math.round(posx/32)*32;
        posy = Math.round(posy/32)*32;
        if(jogador.getGold() >= 10 ){
            if(LevelLoader.getInstance().getMap().getBlock(posx, posy).isAllowTower()){
                t.getLocalizacao().setX(posx);
                t.getLocalizacao().setY(posy);           
                objetos.add(t);
                jogador.setGold(jogador.getGold() - 10);
                mouse.empty();                
            }else{
                JOptionPane.showMessageDialog(null, "Não permitido torre neste bloco");
            }
        }
    }

    public void GameStart(Jogador jogador) {
        this.jogador = jogador;
        initialize();
    }

    private void setLoading(Graphics graphics) {
        
        graphics.setColor(Color.black);
        graphics.drawRect(0, 0, Parametro.SCREEN_HEIGHT,Parametro.SCREEN_WIDTH);
        graphics.fillRect(0, 0, Parametro.SCREEN_HEIGHT,Parametro.SCREEN_WIDTH);
        graphics.setColor(Color.white);
        graphics.drawString("Loading...", Math.abs(Parametro.SCREEN_HEIGHT/2), Math.abs(Parametro.SCREEN_WIDTH/2));
        graphics.setColor(Color.black);
        
    }
    
    private void setPause(Graphics graphics) {
        
        graphics.setColor(Color.black);
        graphics.drawRect(0, 0, Parametro.SCREEN_HEIGHT,Parametro.SCREEN_WIDTH);
        graphics.fillRect(0, 0, Parametro.SCREEN_HEIGHT,Parametro.SCREEN_WIDTH);
        graphics.setColor(Color.white);
        graphics.drawString("Pause..", Math.abs(Parametro.SCREEN_HEIGHT/2), Math.abs(Parametro.SCREEN_WIDTH/2));
        graphics.setColor(Color.black);
        
    }

    public void changeBackground(String value) {
        Graphics g = this.getGraphics();
        g.drawImage(Imagem.getInstance().getResourceImage(value), 0, 0, this);
        
    }

    /**
     * @return the win
     */
    public boolean isWin() {
        return win;
    }

    /**
     * @param win the win to set
     */
    public void setWin(boolean win) {
        this.win = win;
    }

    private void gameOver() {
        SoundFactory.getSoundPlayer().parar();
        CustomBox c = null;
        if(win){    
            SoundFactory.getSoundPlayer().tocar("Ressource/Sound/jiraya.mp3");
            c = new CustomBox(this, true, Imagem.getInstance().getResourceImage("Ressource/Background/jiraya.jpg"),"Voce Perdeu =( ");
        }else{
            SoundFactory.getSoundPlayer().tocar("Ressource/Sound/jiraya.mp3");
            c = new CustomBox(this, true, Imagem.getInstance().getResourceImage("Ressource/Background/jiraya.jpg"),"Parabens, voce venceu!");
        }
        c.setVisible(true);
        SoundFactory.getSoundPlayer().parar();
    }

}
